var sjcl = require('./sjcl.js')
var md5 = require('md5')

function md5(msg){
	return md5(msg)
}

function fb(bits){
	return sjcl.codec.hex.fromBits(bits)
}

function sha1(msg){
	return fb(sjcl.hash.sha1.hash(msg))
}

function sha256(msg){
	return fb(sjcl.hash.sha256.hash(msg))
}

function hmac(msg, key, hash = sjcl.hash.sha256){
	let mac = new sjcl.misc.hmac(sjcl.codec.hex.toBits(key), hash)
	return fb(mac.mac(sjcl.codec.hex.toBits(msg)))
}

function hmacSha1(msg, key){
	return hmac(msg, key, sjcl.hash.sha1)
}

function hmacSha256(msg, key){
	return hmac(msg, key)
}

function pbkdf2(password, salt){
	var seed = sjcl.hash.sha256.hash(password);
	var salt = sjcl.hash.sha256.hash(password + salt);
	var password_kdf_bit = sjcl.misc.pbkdf2(seed, salt);
	return fb(password_kdf_bit)
}

function generateKeypair(password, salt){
	var secret_key = pbkdf2(password, salt)
	var secret_key_bn = new sjcl.bn(secret_key);
	return sjcl.ecc.ecdsa.generateKeys(sjcl.ecc.curves.k256, 0, secret_key_bn);
}

function generateEncKeypair(password, salt){
	var secret_key = pbkdf2(password, salt)
	var secret_key_bn = new sjcl.bn(secret_key);
	return sjcl.ecc.elGamal.generateKeys(sjcl.ecc.curves.k256, 0, secret_key_bn);
}

function publicKey(password, salt){
	var keys = generateKeypair(password, salt);
	return fb(keys.pub.get().x) + fb(keys.pub.get().y)
}

function sign(msg, password, salt){
	var keys = generateKeypair(password, salt);
	var msg_hash = sjcl.hash.sha256.hash(msg);
	var signature = keys.sec.sign(msg_hash, 0);
	return fb(signature)
}

function verify(msg, signature, password, salt){
	var keys = generateKeypair(password, salt);
	
	var msg_hash = sjcl.hash.sha256.hash(msg);
	var signature_hash = sjcl.codec.hex.toBits(signature);
	
	try{
		return keys.pub.verify(msg_hash, signature_hash);
	}catch(e){
		return false;
	}
}

function encrypt(msg, password, salt){
	var keys = generateEncKeypair(password, salt);
	return sjcl.encrypt(keys.pub, msg)
}

function decrypt(ciphertext, password, salt){
	var keys = generateEncKeypair(password, salt);
	return sjcl.decrypt(keys.sec, ciphertext);
}

module.exports = {
	md5,
	sha1,
	sha256,
	hmacSha1,
	hmacSha256,
	pbkdf2,
	publicKey,
	sign,
	verify,
	encrypt,
	decrypt
}